/**
 * Copyright (C) 2010 - 2013 Harry Glasgow
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.jaden.ui.dialog.projectdefinition;

import com.googlecode.jaden.common.config.IOConfiguration;
import com.googlecode.jaden.common.other.Utils;
import com.googlecode.jaden.ui.UiUtils;
import static com.googlecode.jaden.ui.Constants.*;
import com.googlecode.jaden.ui.dialog.BaseDialog;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;

public class EditCategoricalIODialog extends BaseDialog {

    private JList<String> categoriesList;
    private DefaultListModel<String> categoriesListModel;
    private IOConfiguration configuration;
    private JButton editButton;
    private JButton removeButton;
    private JButton moveUpButton;
    private JButton moveDownButton;
    private JCheckBox cyclicCB;

    public EditCategoricalIODialog(EditProjectDefinitionDialog dialog, IOConfiguration configuration,
                                   Preferences preferences, boolean inputMode) {
        super(dialog, DIALOG_PROJECT_DETAILS_CATEGORICAL_TITLE);
        this.configuration = configuration;

        categoriesListModel = new DefaultListModel<String>();
        categoriesList = new JList<String>(categoriesListModel);
        categoriesList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        categoriesList.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() >= 2) {
                    editValue();
                }
            }
        });

        cyclicCB = new JCheckBox(Utils.translate(LABEL_CYCLIC_TEXT));

        for (String string : configuration.getCategoricalList()) {
            categoriesListModel.addElement(string);
        }
        cyclicCB.setSelected(configuration.isCategoricalCyclic());

        JScrollPane scroll = new JScrollPane(categoriesList);
        scroll.setPreferredSize(new Dimension(200, 125));
        JPanel mainPanel;
        if (inputMode) {
            mainPanel = UiUtils.verticalList(UiUtils.horizontalList(scroll), UiUtils.horizontalList(cyclicCB));
        } else {
            mainPanel = UiUtils.verticalList(
                    UiUtils.horizontalList(scroll));
        }
        setMainPanel(mainPanel, preferences);

        JButton addButton = UiUtils.createButton(LABEL_ADD_TEXT);
        editButton = UiUtils.createButton(LABEL_EDIT_TEXT);
        removeButton = UiUtils.createButton(LABEL_REMOVE_TEXT);
        moveUpButton = UiUtils.createButton(LABEL_MOVE_UP_TEXT);
        moveDownButton = UiUtils.createButton(LABEL_MOVE_DOWN_TEXT);

        addButton(addButton);
        addButton(editButton);
        addButton(removeButton);
        addButton(moveUpButton);
        addButton(moveDownButton);

        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addValue();
            }
        });

        editButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                editValue();
            }
        });

        removeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                removeValue();
            }
        });

        moveUpButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                moveUp();
            }
        });

        moveDownButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                moveDown();
            }
        });

        categoriesList.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                enableButtons();
            }
        });

        enableButtons();
    }

    private void enableButtons() {
        editButton.setEnabled(categoriesList.getSelectedIndex() >= 0);
        removeButton.setEnabled(categoriesList.getSelectedIndex() >= 0);
        moveUpButton.setEnabled(categoriesList.getSelectedIndex() > 0);
        moveDownButton.setEnabled(categoriesList.getSelectedIndex() >= 0 &&
                categoriesList.getSelectedIndex() < categoriesListModel.getSize() - 1);
    }

    private void addValue() {
        AddEditCategoricalIOEntryDialog dialog = new AddEditCategoricalIOEntryDialog(this, "", getPreferences());
        dialog.setVisible(true);
    }

    private void moveUp() {
        int bottomIndex = categoriesList.getSelectedIndex();
        int topIndex = categoriesList.getSelectedIndex() - 1;
        String bottom = categoriesListModel.get(bottomIndex);
        String top = categoriesListModel.get(topIndex);
        categoriesListModel.setElementAt(bottom, topIndex);
        categoriesListModel.setElementAt(top, bottomIndex);
        categoriesList.setSelectedIndex(topIndex);
    }

    private void moveDown() {
        int topIndex = categoriesList.getSelectedIndex();
        int bottomIndex = categoriesList.getSelectedIndex() + 1;
        String top = categoriesListModel.get(topIndex);
        String bottom = categoriesListModel.get(bottomIndex);
        categoriesListModel.setElementAt(bottom, topIndex);
        categoriesListModel.setElementAt(top, bottomIndex);
        categoriesList.setSelectedIndex(bottomIndex);
    }

    private void editValue() {
        AddEditCategoricalIOEntryDialog dialog = new AddEditCategoricalIOEntryDialog(this,
                categoriesListModel.getElementAt(categoriesList.getSelectedIndex()), getPreferences());
        dialog.setVisible(true);
    }

    public void update(String original, String changed) {
        if (original.equals(changed)) {
            return;
        }
        int i = categoriesListModel.indexOf(original);
        if (i >= 0) {
            categoriesListModel.set(i, changed);
        } else {
            categoriesListModel.addElement(changed);
        }
    }

    private void removeValue() {
        categoriesListModel.removeElementAt(categoriesList.getSelectedIndex());
    }

    protected void doOk() {
        if (categoriesListModel.getSize() < 2) {
            JOptionPane.showMessageDialog(this, Utils.translate(ERROR_NO_CATEGORIES));
        } else {
            List<String> values = new ArrayList<String>();
            for (int i = 0; i < categoriesListModel.getSize(); i++) {
                String val = categoriesListModel.elementAt(i);
                if (values.contains(val)) {
                    JOptionPane.showMessageDialog(this, Utils.translate(ERROR_DUPLICATE_VALUES));
                    return;
                }
                values.add(val);
            }
            configuration.getCategoricalList().clear();
            for (int i = 0; i < categoriesListModel.getSize(); i++) {
                configuration.getCategoricalList().add(categoriesListModel.elementAt(i));
            }
            configuration.setCategoricalCyclic(cyclicCB.isSelected());
            dispose();
        }
    }
}